﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SimioAPI;
using SimioAPI.Extensions;
using System.Windows.Forms;

namespace WLC
{
    class WLCSequenceElementDefinition : IElementDefinition
    {
        #region IElementDefinition Members

        public IElement CreateElement(IElementData data)
        {
            return new WLCSequenceElement(data);
        }


        public void DefineSchema(IElementSchema schema)
        {
            IPropertyDefinitions propSchema = schema.PropertyDefinitions;
            IPropertyDefinitions repProp = propSchema.AddRepeatGroup("WLCSequence", "");
            
            IPropertyDefinition no =  repProp.AddStringProperty("No", String.Empty);
            no.Description = "The number of the workstation node in the sequence. The first workstation to visit must be assigned the number 1";
            no.Required = true;
            
            IPropertyDefinition workstationName = repProp.AddStringProperty("WorkstationName", String.Empty);
            workstationName.Description = "The name of the workstation object.";
            workstationName.Required = true;

            IPropertyDefinition nodeID = repProp.AddExpressionProperty("NodeID", String.Empty);
            nodeID.Description = "The expression returning the integer ID of the node.";
            nodeID.Required = true;

            IPropertyDefinition processingTime = repProp.AddExpressionProperty("ProcessingTime", String.Empty);
            processingTime.Description = "The expression determining the order's processing time at the workstation.";
            processingTime.Required = true;
                        

            IStateDefinitions stateSchema = schema.StateDefinitions;

            IStateDefinition currentNodeID = stateSchema.AddState("currentNodeID");
            currentNodeID.Description = "The integer ID of the current node the WLCOrder is at.";
            

            IStateDefinition currentSeqNo = stateSchema.AddState("currentSequenceNo");
            currentSeqNo.Description = "The number of the current workstation in the sequence the WLCOrder is at.";
            
            IStateDefinition currentProcessingTime = stateSchema.AddState("currentProcessingTime");
            currentProcessingTime.Description = "The processing time at the current workstation in the sequence the WLCOrder is at.";

            IStateDefinition totalProcessingTime = schema.StateDefinitions.AddState("TotalProcessingTime");
            totalProcessingTime.Description = "The sum of all processing times in that BOM. The size of the order is not included.";

                        
        }


        public string Name
        {
            get { return "WLCSequence"; }
        }

        public string Description
        {
            get { return ""; }
        }

        public System.Drawing.Image Icon
        {
            get { return null; }
        }


   
        // We need to use this ID in the element reference property of the Open/Close/PassThru steps, so we make it public
        public static readonly Guid ID = new Guid("{4A2A4B52-0535-11DF-BBCE-5A5556D89593}");

        public Guid UniqueID
        {
            get { return ID; }
        }

        #endregion
    }


    public class WLCSequenceElement : IElement
    {
        IElementData _data;
        IRepeatingPropertyReader _wlcSequence;
        public string ReservedFor { get; set; }
     
        public WLCSequenceElement(IElementData data)
        {
            _wlcSequence = (IRepeatingPropertyReader) data.Properties.GetProperty("WLCSequence");
            _data = data;
            ReservedFor = null;
                     
        }
        
        #region IElement Members

        public string GetCurrentWorkstationName() {
            string currentWorkstationName = "";
           
            int currentNo = (int)_data.States["currentSequenceNo"].StateValue;

            IPropertyReaders currentRow;

            for (int i = 0; i < _wlcSequence.GetCount(_data.ExecutionContext); i++)
            {
                currentRow = _wlcSequence.GetRow(i, _data.ExecutionContext);
                
                int compare = int.Parse(currentRow.GetProperty("No").GetStringValue(_data.ExecutionContext));

                if (compare == currentNo)
                {
                    return currentWorkstationName = currentRow.GetProperty("WorkstationName").GetStringValue(_data.ExecutionContext);
                    
                }
            }

            return currentWorkstationName;


        }

        public bool HasNext()
        {
            bool result = true;
            
            int currentNo = (int)_data.States["currentSequenceNo"].StateValue;

         
         
            if (_wlcSequence.GetCount(_data.ExecutionContext) <= currentNo)
                result = false;
            

            return result;
        }



        public int GetNumberOfSteps() {

            return _wlcSequence.GetCount(_data.ExecutionContext);

        }


        public void UpdateProcessingTime(double orderSize)
        {
            int currentNo = (int)_data.States["currentSequenceNo"].StateValue;
            IPropertyReaders row = _wlcSequence.GetRow(currentNo, _data.ExecutionContext);
            _data.States["currentProcessingTime"].StateValue = row.GetProperty("ProcessingTime").GetDoubleValue(_data.ExecutionContext) * orderSize;
        }


        public int GetSequenceNo(int index)
        {

            IPropertyReaders row = _wlcSequence.GetRow(index, _data.ExecutionContext);
            return int.Parse(row.GetProperty("No").GetStringValue(_data.ExecutionContext));
        }


        public string GetSequenceWorkstationName(int index)
        {
            IPropertyReaders row = _wlcSequence.GetRow(index, _data.ExecutionContext);

            return row.GetProperty("WorkstationName").GetStringValue(_data.ExecutionContext);
        }


        public double GetSequenceProcessingTime(int index)
        {
            
            IPropertyReaders row = _wlcSequence.GetRow(index, _data.ExecutionContext); 
            return row.GetProperty("ProcessingTime").GetDoubleValue(_data.ExecutionContext);
        }

        public int GetSequenceCount()
        {
            return _wlcSequence.GetCount(_data.ExecutionContext);
        }


        public int GetCurrentNo()
        {
            return (int)_data.States["currentSequenceNo"].StateValue;
        }

        public void SetInitial(double orderSize)
        {
            // Initially set the currentSequenceNo to one and set the currentNodeID to the first NodeID
            IRepeatingPropertyReader wlcSequence = (IRepeatingPropertyReader) _data.Properties.GetProperty("WLCSequence");
            IPropertyReaders firstRow = wlcSequence.GetRow(0, _data.ExecutionContext);

            _data.States["currentSequenceNo"].StateValue = 1;
            _data.States["currentNodeID"].StateValue = firstRow.GetProperty("NodeID").GetDoubleValue(_data.ExecutionContext);
            _data.States["currentProcessingTime"].StateValue = firstRow.GetProperty("ProcessingTime").GetDoubleValue(_data.ExecutionContext) * orderSize;
       
        }

        public int MoveNext(double orderSize)
        {
            if (HasNext())
            {                
              

                int currentNo = (int)_data.States["currentSequenceNo"].StateValue;
                                              
                IPropertyReaders row = _wlcSequence.GetRow(currentNo, _data.ExecutionContext);
                    
                       
                _data.States["currentNodeID"].StateValue = row.GetProperty("NodeID").GetDoubleValue(_data.ExecutionContext);
                _data.States["currentSequenceNo"].StateValue = int.Parse(row.GetProperty("No").GetStringValue(_data.ExecutionContext));
                _data.States["currentProcessingTime"].StateValue = row.GetProperty("ProcessingTime").GetDoubleValue(_data.ExecutionContext) * orderSize;
               

                return (int)_data.States["currentNodeID"].StateValue;
            }
            return -1;

        }


      public void Initialize()
        {
            _data.States["TotalProcessingTime"].StateValue = 0;

            int BOMsize = _wlcSequence.GetCount(_data.ExecutionContext);
            IPropertyReaders currentRow;

            for (int i = 0; i < BOMsize ; i++)
            {
                currentRow = _wlcSequence.GetRow(i, _data.ExecutionContext);
                _data.States["TotalProcessingTime"].StateValue += currentRow.GetProperty("ProcessingTime").GetDoubleValue(_data.ExecutionContext);

            }

          
           
        }
        

        public void Shutdown()
        {
            // No shutdown code necessary
        }

        #endregion
    }



    }

